<template>
  <view class="gi-form">
    <sar-form ref="formRef" :model="props.modelValue" scroll-to-first-error>
      <template v-for="(item, index) in props.columns" :key="index">
        <template v-if="item.slotName">
          <slot :name="item.slotName"></slot>
        </template>
        <template v-if="item.type === 'group-title'">
          <sar-alert :key="item.field">{{ item.label }}</sar-alert>
        </template>
        <template v-else>
          <sar-form-item v-if="!isHide(item)" :key="item.field" :label="item.label" :name="item.field" :rules="item.rules">
            <!-- 使用条件渲染替代动态组件 -->
            <sar-input
              v-if="item.type === 'input'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-input
              v-else-if="item.type === 'textarea'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-picker-input
              v-else-if="item.type === 'picker'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-stepper
              v-else-if="item.type === 'stepper'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <gi-form-datetime-picker
              v-else-if="item.type === 'datetime-picker'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <gi-form-calendar
              v-else-if="item.type === 'calendar'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-checkbox-input
              v-else-if="item.type === 'checkbox-input'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-checkbox
              v-else-if="item.type === 'checkbox-group'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-radio-input
              v-else-if="item.type === 'radio-input'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-radio-group
              v-else-if="item.type === 'radio-group'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-popout-input
              v-else-if="item.type === 'popout-input'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-rate
              v-else-if="item.type === 'rate'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-slider
              v-else-if="item.type === 'slider'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-switch
              v-else-if="item.type === 'switch'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
            <sar-upload
              v-else-if="item.type === 'upload'"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            />
          </sar-form-item>
        </template>
      </template>
    </sar-form>
  </view>
</template>

<script lang='ts' setup>
import type { FormRules } from 'sard-uniapp'
import type Form from 'sard-uniapp/components/form/form.vue'
import type { ColumnItem, ColumnItemProps, ColumnItemType } from './type'

interface Props {
  modelValue: any
  columns: ColumnItem[]
  rules?: FormRules
  readonly?: boolean // 表单只读
}

const props = withDefaults(defineProps<Props>(), {
  columns: () => [],
  fc: () => ({}),
  readonly: false,
})

const emit = defineEmits<{
  (e: 'update:modelValue', value: any): void
}>()

const formRef = ref<InstanceType<typeof Form>>()

function updateModelValue(value: any, item: ColumnItem) {
  emit('update:modelValue', Object.assign(props.modelValue, { [item.field]: value }))
}

function getPlaceholder(item: ColumnItem) {
  if (
    ['popout-input'].includes(item.type)
  ) {
    return `请选择${item.label}`
  }
  else if (['textarea'].includes(item.type)) {
    return `请填写${item.label}`
  }
  else {
    return `请输入${item.label}`
  }
}

function getComponentProps(item: ColumnItem) {
  const defaultComponentProps: Record<ColumnItemType, ColumnItemProps> = {
    'input': { clearable: false },
    'textarea': { type: 'textarea', clearable: false, showCount: true, maxlength: 200 },
    'datetime-picker': { type: 'yMdhms' },
    'stepper': { size: 'small', placeholder: '' },
  }
  const obj: any = {
    placeholder: getPlaceholder(item),
    ...defaultComponentProps[item.type],
  }
  return { ...obj, ...item.props }
}

function isHide(item: ColumnItem) {
  if (item.hide === undefined)
    return false
  if (typeof item.hide === 'boolean')
    return item.hide
  if (typeof item.hide === 'function') {
    return item.hide(props.modelValue)
  }
}

function isReadonly(item: ColumnItem) {
  if (props?.readonly === true)
    return true
  if (typeof item?.readonly === 'boolean')
    return item.readonly
  if (typeof item?.readonly === 'function') {
    return item?.readonly(props.modelValue)
  }
  return false
}

function isDisabled(item: ColumnItem) {
  if (item.disabled === undefined)
    return false
  if (typeof item.disabled === 'boolean')
    return item.disabled
  if (typeof item.disabled === 'function') {
    return item.disabled(props.modelValue)
  }
}

watch(
  () => props.modelValue,
  () => {
  },
  { immediate: true, deep: true },
)

defineExpose({ formRef })
</script>

<style lang='scss' scoped>

</style>
